package org.west.sky.scripture.ratelimiter;

import java.time.LocalTime;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author chz
 * @date 2022/3/18
 * @description: 固定窗口限流算法
 */
public class FixedWindowRateLimiter {

    /**
     * 阈值
     */
    private static Integer QPS = 2;
    /**
     * 时间窗口（毫秒）
     */
    private static long TIME_WINDOWS = 1000;
    /**
     * 计数器
     */
    private static AtomicInteger REQUEST_COUNT = new AtomicInteger();
    /**
     * 开始时间
     */
    private static long start_time = System.currentTimeMillis();

    /**
     * 判断请求是否可以通过
     *
     * @return
     */
    public synchronized static boolean tryAcquire() {
        if (System.currentTimeMillis() - start_time > TIME_WINDOWS) {
            REQUEST_COUNT.set(0);
            start_time = System.currentTimeMillis();
        }
        return REQUEST_COUNT.incrementAndGet() <= QPS;
    }

    public static void main(String[] args) throws InterruptedException {
//        testOne();
        testTwo();
    }

    /**
     * 正常情况下1秒执行3次，阈值为2，所以有1次被限流
     *
     * @throws InterruptedException
     */
    public static void testOne() throws InterruptedException {
        for (int i = 0; i < 10; i++) {
            Thread.sleep(250);
            LocalTime time = LocalTime.now();
            if (!tryAcquire()) {
                System.out.println(time + " 被限流了！！");
            } else {
                System.out.println(time + " 做点什么！！");
            }
        }
    }

    /**
     * 当遇到窗口临界突变时，如第1s的后500ms和第2s的前500ms,加起来虽然是1s,但是却请求了4次
     *
     * @throws InterruptedException
     */
    public static void testTwo() throws InterruptedException {
        Thread.sleep(400);
        for (int i = 0; i < 10; i++) {
            Thread.sleep(250);
            LocalTime time = LocalTime.now();
            if (!tryAcquire()) {
                System.out.println(time + " 被限流了！！");
            } else {
                System.out.println(time + " 做点什么！！");
            }
        }
    }
}
